Since 2015, JavaScript has improved immensely.
It’s much more pleasant to use it now than ever.
In this article, we’ll look at JavaScript generators.
Kinds of Generators
There’re various kinds of generators.
We can define generators as generator function declarations.
This takes the form of:
function* genFn() {
//...
}
const genObj = genFn();
Generator function expressions are where we assign our generator function to a variable:
const genFn = function*() {
//...
}
const genObj = genFn();
Generator methods in object literals let us create generator methods:
const obj = {
* gen() {
//...
}
};
const genObj = obj.gen();
Generator methods can also be in classes.
For example, we can write:
class Foo {
* gen() {
//..,
}
}
const foo = new Foo();
const genObj = foo.gen();
We create a class and add the gen
method which is the generator method.
We can use generator functions to create our own iterable object.
For instance, we can write:
function* keys(obj) {
const propKeys = Reflect.ownKeys(obj);
for (const propKey of propKeys) {
yield propKeys;
}
}
const obj = {
a: 1,
b: 2
};
for (const key of keys(obj)) {
console.log(key);
}
We create the keys
generator function, which gets the keys from an object and returns the keys.
Then we loop through the keys with the for-of loop.
async
and await
also uses generators underneath,.
await
works like yield
in that it pauses the code until the result is retrieved.
The syntax also uses generators under the surface.
For instance, we can use it by writing:
async function fetchJson(url) {
try {
const request = await fetch(url);
const res = await request.json();
return res;
} catch (error) {
console.log(error);
}
}
async functions only return promises.
The return
statement returns a promise that resolves to the value returned.
Generators
Generators are functions that can be paused and resumed.
Generators are the only functions that can return generators.
So if we have a generator function, we can write:
function* keys(obj) {
const propKeys = Reflect.ownKeys(obj);
for (const propKey of propKeys) {
yield propKeys;
}
}
const obj = {
a: 1,
b: 2
};
const gen = keys(obj)
We call the keys
genereator function to return a generator.
The generator is gen
and ot’s not run until we call next
.
For example, if we have:
const gen = keys(obj);
console.log(gen.next());
console.log(gen.next());
Then the generator function will run.
Uses of Generators
Generators can be used for iterators.
They produce data with yield
and it can be accessed with the next
method.
Generators can produce sequences of values with loops and recursion.
This means that generators can be used with the for-of and the spread operator.
They can also be data consumers.
yield
can get values from the next
method or any other sources.
They can also be both at the same time since they can be paused.
Conclusion
Generators can be data producers and consumers.
async
and await
also uses the generator syntax underneath the surface.